package util

import (
	"archive/tar"
	"io"
	"os"
	"path/filepath"
	"strings"
)

/***生成***/
func CreateTar(filesource, filetarget string) (*tar.Writer, error) {
	tarfile, err := os.Create(filetarget)
	if err != nil {
		if err == os.ErrExist {
			if err := os.Remove(filetarget); err != nil {
				return nil, err
			}
		} else {
			return nil, err
		}
	}
	//defer tarfile.Close()
	tarwriter := tar.NewWriter(tarfile)
	sfileInfo, err := os.Stat(filesource)
	if err != nil {
		return nil, err
	}
	if !sfileInfo.IsDir() {
		return TarFile(filetarget, filesource, sfileInfo, tarwriter)
	} else {
		return TarFolder(filesource, tarwriter)
	}
}

//
func TarFile(directory string, filesource string, sfileInfo os.FileInfo, tarwriter *tar.Writer) (*tar.Writer, error) {
	sfile, err := os.Open(filesource)
	if err != nil {
		return nil, err
	}
	defer sfile.Close()
	header, err := tar.FileInfoHeader(sfileInfo, "")
	if err != nil {
		return nil, err
	}
	header.Name = directory
	err = tarwriter.WriteHeader(header)
	if err != nil {
		return nil, err
	}
	//  can use buffer to copy the file to tar writer
	//    buf := make([]byte,15)
	//    if _, err = io.CopyBuffer(tarwriter, sfile, buf); err != nil {
	//        panic(err)
	//        return err
	//    }
	if _, err = io.Copy(tarwriter, sfile); err != nil {
		return nil, err
	}
	return tarwriter, nil
}
func TarFolder(directory string, tarwriter *tar.Writer) (*tar.Writer, error) {
	var baseFolder string = filepath.Base(directory)
	err := filepath.Walk(directory, func(targetpath string, file os.FileInfo, err error) error {
		//read the file failure
		if file == nil {
			return err
		}
		if file.IsDir() {
			//if file.Name() == ".git" || file.Name() == "node_modules" || file.Name() == "__MACOSX" {
			if file.Name() == "__MACOSX" {
				return filepath.SkipDir
			}

			// information of file or folder
			header, err := tar.FileInfoHeader(file, "")
			if err != nil {
				return err
			}
			header.Name = filepath.Join(baseFolder, strings.TrimPrefix(targetpath, directory))
			if err = tarwriter.WriteHeader(header); err != nil {
				return err
			}
			//os.Mkdir(strings.TrimPrefix(baseFolder, file.Name()), os.ModeDir)
			return nil
		} else {
			//baseFolder is the tar file path
			var fileFolder = filepath.Join(baseFolder, strings.TrimPrefix(targetpath, directory))
			_, err = TarFile(fileFolder, targetpath, file, tarwriter)
			return err
		}
	})
	if err != nil {
		return nil, err
	}
	return tarwriter, nil
}
